﻿package component.formula.function;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import component.formula.FormulaInfo;
import component.formula.constant.FormulaConstant;
import component.formula.constant.TreeConstant;
import component.formula.exception.FormulaException;
import component.formula.util.FormulaUtil;

/**
 * 动态行
 */
public class ListType implements IReportType {
	public List parser(List formulaList, Map dataMap) throws FormulaException {
		Map map = new HashMap();

		FormulaInfo firstParserFormula = null;
		List formulaObjList = new ArrayList();
		for (int i = 0; i < formulaList.size(); i++) {
			String formula = (String) formulaList.get(i);
			FormulaInfo formulaInfo = FormulaUtil.strToFormulObj(formula);
			formulaInfo.setColNum(i);

			if (formula.indexOf("tree") != -1) {
				firstParserFormula = formulaInfo;
			} else {
				formulaObjList.add(formulaInfo);
			}
		}
		if (firstParserFormula == null) {
			firstParserFormula = (FormulaInfo) formulaObjList.get(0);
			formulaObjList.remove(0);
		}

		// 先解析树型公式
		String dsName = firstParserFormula.getDsName();
		List dataList = (List) dataMap.get(dsName);
		// System.out.println("计算前的总数：" + dataList.size());
		IReportFunction function = (IReportFunction) FunctionLib.funClassMap
				.get(firstParserFormula.getFunctionName());
		List retList = (List) function.calculate(firstParserFormula
				.getParaExpression(), firstParserFormula, dataList);
		// System.out.println("计算后的总数：" + retList.size());
		for (int i = 0; i < retList.size(); i++) {
			Map rowMap = (Map) retList.get(i);
			String compareValue = (String) rowMap
					.get(FormulaConstant.COMPARE_NAME);

			// 解析后面的所有公式
			for (int j = 0; j < formulaObjList.size(); j++) {
				FormulaInfo currentFormula = (FormulaInfo) formulaObjList
						.get(j);
				String expression = currentFormula.getParaExpression();
				String[] paraArr = expression.split(",");
				String colName = paraArr[0].trim(); // 显示的字段名
				String compareName = ""; // 与左边比较的字段名
				String isSum = ""; // 如果是树型, 是否向上汇总
				if (paraArr.length > 1) {
					compareName = paraArr[1].trim();
				}
				if (paraArr.length > 2) {
					isSum = paraArr[2].trim();
				}

				if (currentFormula.getDsName().equals(dsName)) { // 同一个数据源
					rowMap.put(String.valueOf(currentFormula.getColNum()),
							rowMap.get(colName));
				} else {
					Map currentDsMap = (Map) map.get(dsName);
					if (currentDsMap == null) { // 将每行的数据放入map中, key为比较的值,
												// value为行值map
						currentDsMap = new HashMap();
						List dsList = (List) dataMap.get(currentFormula
								.getDsName());
						for (int k = 0; k < dsList.size(); k++) {
							Map currentRowMap = (Map) dsList.get(k);
							String currentCompareValue = String
									.valueOf(currentRowMap.get(compareName));
							currentDsMap
									.put(currentCompareValue, currentRowMap);
						}
						map.put(dsName, currentDsMap);
					}
					Map currentRowMap = (Map) currentDsMap.get(compareValue);
					if (currentRowMap != null) {
						Object currentValue = currentRowMap.get(colName);
						if ("true".equals(isSum) && currentValue != null) { // 向上汇总
							Integer parentPosition = (Integer) rowMap
									.get(TreeConstant.PARENT_POSITION_NAME); // 父节点的位置
							Map parentRowMap = null;
							while (parentPosition != null) {
								parentRowMap = (Map) retList.get(parentPosition
										.intValue());
								// System.out.println("父节点的位置：" +
								// parentPosition);
								// 汇总父节点
								if (currentValue instanceof BigDecimal) {
									BigDecimal parentValue = (BigDecimal) parentRowMap
											.get(String.valueOf(currentFormula
													.getColNum()));
									if (parentValue == null) {
										parentValue = new BigDecimal("0");
									}
									BigDecimal currentValueTemp = (BigDecimal) currentValue;
									if (currentValueTemp == null)
										currentValueTemp = new BigDecimal("0");
									// System.out.println("parentValue = " +
									// parentValue + ", currentValue = " +
									// currentValueTemp );
									parentValue = parentValue
											.add(currentValueTemp);
									// System.out.println("计算后的金额 = " +
									// parentValue);
									parentRowMap.put(
											String.valueOf(currentFormula
													.getColNum()), parentValue);
								} else if (currentValue instanceof Integer) {
									Integer parentValue = (Integer) parentRowMap
											.get(String.valueOf(currentFormula
													.getColNum()));
									if (parentValue == null) {
										parentValue = new Integer(0);
									}
									Integer currentValueTemp = (Integer) currentValue;
									if (currentValueTemp == null)
										currentValueTemp = new Integer(0);
									parentValue = new Integer(parentValue
											.intValue()
											+ currentValueTemp.intValue());
									parentRowMap.put(
											String.valueOf(currentFormula
													.getColNum()), parentValue);
								}

								parentPosition = (Integer) parentRowMap
										.get(TreeConstant.PARENT_POSITION_NAME); // 父节点的位置
							}

						}
						rowMap.put(String.valueOf(currentFormula.getColNum()),
								currentValue);
					}
				}
			}
		}
		return retList;
	}
	
	private static Map getDataMap(){
		Map map = new HashMap();
		
		//sql1对应的数据
		List dataList1 = new ArrayList();
		
		Map rowMap = null;
		for(int i = 0;i<10000;i++){
			rowMap = new HashMap();
			rowMap.put("id", "100" + i);
			rowMap.put("code", "code" + i);
			rowMap.put("name", "name" + i);
			dataList1.add(rowMap);
		}
		map.put("ds1", dataList1);
		
		//sql2对应的数据
		List dataList2 = new ArrayList();
		
		Map rowMap2 = null;
		for(int i = 0;i<10000;i++){
			rowMap2 = new HashMap();
			rowMap2.put("fid", "100" + i);
			rowMap2.put("money", new BigDecimal(i));
			dataList2.add(rowMap2);
		}
		map.put("ds2", dataList2);
		
		return map;
	}
	
	private static Map getTreeDataMap(){
		Map map = new HashMap();
		
		//sql1对应的数据
		List dataList1 = new ArrayList();
		//sql2对应的数据
		List dataList2 = new ArrayList();
		
		Map rowMap = null;
		Map rowMap2 = null;
		for(int i = 1;i<3;i++){ // 不能从 0 开始 , 0是根节点
			rowMap = new HashMap();
			rowMap.put("id", "" + i);
			rowMap.put("code", "code" + i);
			rowMap.put("name", "name" + i);
			rowMap.put("parentId", "0");
			rowMap.put("order", String.valueOf(i));
			dataList1.add(rowMap);
			
			//第二层数据
			for(int j = 100; j<112;j++){
				rowMap = new HashMap();
				rowMap.put("id", i + "_" + j);
				rowMap.put("code", "code" + i + "_" + j);
				rowMap.put("name", "name" + i + "_"+ j);
				rowMap.put("parentId", "" + i);
				rowMap.put("order", String.valueOf(j));
				dataList1.add(rowMap);
				
				//第三层数据
				for(int k = 1050; k>=1000;k--){
					rowMap = new HashMap();
					rowMap.put("id", i + "_" + j + "_" + k);
					rowMap.put("code", "code" + i + "_" + j + "_" + k);
					rowMap.put("name", "name"  + i + "_" + j + "_" + k);
					rowMap.put("parentId", i + "_" + j);
					rowMap.put("order", String.valueOf(k));
					dataList1.add(rowMap);
					
					rowMap2 = new HashMap();
					rowMap2.put("fid", i + "_" + j + "_" + k);
					rowMap2.put("money", new BigDecimal(k).setScale(2));
					rowMap2.put("person", new Integer(k));
					dataList2.add(rowMap2);
				}
			}
			
		}
		map.put("ds1", dataList1);
		map.put("ds2", dataList2);
		System.out.println("总数：" + dataList1.size());
		
		return map;
	}
	
	private static void testSelect() throws FormulaException{
		long begin = System.currentTimeMillis();
		
		List formulaList = new ArrayList();
		formulaList.add("ds1.select(code,id)");
		formulaList.add("ds1.select(name)");
		formulaList.add("ds2.select(money, fid)");
		
		System.out.println();
		IReportType reportType = new ListType();
		List retList = reportType.parser(formulaList, getDataMap());
		for(int i = 0;i<retList.size();i++){
			Map rowMap = (Map)retList.get(i);
			for(int j = 0;j<formulaList.size();j++){
				System.out.print(rowMap.get(String.valueOf(j)) + "  ");
			}
			System.out.println();
		}
		
		System.out.println("时间： "
				+ String.valueOf((System.currentTimeMillis() - begin)/1000));
	}
	
	private static void testTree() throws FormulaException{
		long begin = System.currentTimeMillis();
		
		List formulaList = new ArrayList();
		//formulaList.add("ds1.select(code)");
		formulaList.add("ds1.tree(name, id ,parentId, 0, order)");
		formulaList.add("ds2.select(money, fid, true)");
		formulaList.add("ds2.select(person, fid, true)");
		
		System.out.println();
		IReportType reportType = new ListType();
		List retList = reportType.parser(formulaList, getTreeDataMap());
		for(int i = 0;i<retList.size();i++){
			Map rowMap = (Map)retList.get(i);
			for(int j = 0;j<formulaList.size();j++){
				System.out.print(rowMap.get(String.valueOf(j)) + "  ");
			}
			System.out.print("  " + rowMap.get("level"));
			System.out.println();
		}
		
		System.out.println("时间： "
				+ String.valueOf((System.currentTimeMillis() - begin)/1000));
	}
	
	public static void main(String[] args) throws FormulaException {
		//testSelect();
		
		testTree();
	}
}
